package handler

import (
	"net/http"
	"strconv"
	"strings"
	"trace-rule/internal/domain/model"
	"trace-rule/internal/dto/request"
	"trace-rule/internal/dto/response"
	"trace-rule/internal/service"

	"github.com/gin-gonic/gin"
)

type RuleHandler struct {
	service *service.RuleService
}

func NewRuleHandler(service *service.RuleService) *RuleHandler {
	return &RuleHandler{service: service}
}

func (h *RuleHandler) CreateRule(c *gin.Context) {
	var req request.CreateRuleRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	rule := &model.Rule{
		Symbol:        req.Symbol,
		MinOperator:   req.MinOperator,
		MinValue:      req.MinValue,
		MaxOperator:   req.MaxOperator,
		MaxValue:      req.MaxValue,
		EmailTemplate: req.EmailTemplate,
		Interval:      req.Interval,
		IsEnabled:     req.IsEnabled,
		TargetEmails:  strings.Join(req.TargetEmails, ","),
	}

	if err := h.service.CreateRule(rule); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusCreated, response.ToRuleResponse(rule))
}

func (h *RuleHandler) UpdateRule(c *gin.Context) {
	id, _ := strconv.ParseUint(c.Param("id"), 10, 32)

	var req request.UpdateRuleRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	rule := &model.Rule{
		Symbol:        req.Symbol,
		MinOperator:   req.MinOperator,
		MinValue:      req.MinValue,
		MaxOperator:   req.MaxOperator,
		MaxValue:      req.MaxValue,
		EmailTemplate: req.EmailTemplate,
		Interval:      req.Interval,
		IsEnabled:     req.IsEnabled,
		TargetEmails:  strings.Join(req.TargetEmails, ","),
	}
	rule.ID = uint(id)

	if err := h.service.UpdateRule(rule); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, response.ToRuleResponse(rule))
}

func (h *RuleHandler) DeleteRule(c *gin.Context) {
	id, _ := strconv.ParseUint(c.Param("id"), 10, 32)
	if err := h.service.DeleteRule(uint(id)); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "Rule deleted successfully"})
}

func (h *RuleHandler) GetRule(c *gin.Context) {
	id, _ := strconv.ParseUint(c.Param("id"), 10, 32)
	rule, err := h.service.GetRule(uint(id))
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Rule not found"})
		return
	}

	c.JSON(http.StatusOK, response.ToRuleResponse(rule))
}

func (h *RuleHandler) ListRules(c *gin.Context) {
	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(c.DefaultQuery("pageSize", "10"))

	rules, total, err := h.service.ListRules(page, pageSize)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, response.ToRuleListResponse(rules, total))
}

func (h *RuleHandler) ListEnabledRules(c *gin.Context) {
	rules, err := h.service.ListEnabledRules()
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, response.ToRuleListResponse(rules, int64(len(rules))))
}
